package com.atguigu.paymentdemo.config;

import cn.hutool.core.codec.Base64;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.params.HttpParams;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

@Component
@Slf4j
public class WXPayUtils {

    @Autowired
    private MyWXPayConfig myWXPayConfig;
    @Autowired
    private WeChatConfig weChatConfig;

    private static final String APPLICATION_JSON = "application/json";
    private static final String requestBody = "{\n"
            + "    \"stock_id\": \"9433645\",\n"
            + "    \"stock_creator_mchid\": \"1900006511\",\n"
            + "    \"out_request_no\": \"20190522_001中文11\",\n"
            + "    \"appid\": \"wxab8acb865bb1637e\"\n"
            + "}";
    private CloseableHttpClient httpClient;

    public void setup() {
        PrivateKey merchantPrivateKey = weChatConfig.getPrivateKey();
        X509Certificate wechatPayCertificate = weChatConfig.getCertificate();

        ArrayList<X509Certificate> listCertificates = new ArrayList<>();
        listCertificates.add(wechatPayCertificate);

        WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
                .withMerchant(myWXPayConfig.getMchID(), myWXPayConfig.getMchSerialNo(), merchantPrivateKey)
                .withWechatPay(listCertificates);
        httpClient = builder.build();
    }

    /**
     * wxMchid商户号
     * wxCertno证书编号
     * wxCertPath证书地址
     * wxPaternerKey   v3秘钥
     * url jsapi下单地址
     * body 构造好的消息体
     */
    public Map<String, Object> doPostWexinV3(String url, String body) {
        if (httpClient == null) {
            setup();
        }

        HttpPost httpPost = new HttpPost(url);
        httpPost.addHeader("Content-Type", "application/json;chartset=utf-8");
        httpPost.addHeader("Accept", "application/json");
        try {
            if (body == null) {
                throw new IllegalArgumentException("data参数不能为空");
            }
            log.info("body:{}",body);
            StringEntity stringEntity = new StringEntity(body, "utf-8");
            httpPost.setEntity(stringEntity);
            // 直接执行execute方法，官方会自动处理签名和验签，并进行证书自动更新
            HttpResponse httpResponse = httpClient.execute(httpPost);
            HttpEntity httpEntity = httpResponse.getEntity();

            if (httpResponse.getStatusLine().getStatusCode() == 200) {
                String jsonResult = EntityUtils.toString(httpEntity);
                log.info("返回信息====："+jsonResult);
                Map map = JSON.parseObject(jsonResult, HashMap.class);
                Header[] allHeaders = httpResponse.getAllHeaders();

                for (Header allHeader : allHeaders) {
                    switch (allHeader.getName()) {
                        case "Wechatpay-Nonce":
                            map.put("nonceStr",allHeader.getValue());
                            break;
                        case "Wechatpay-Signature-Type":
                            map.put("signType",allHeader.getValue());
                            break;
                        case "Wechatpay-Signature":
                            map.put("paySign",allHeader.getValue());
                            break;
                        case "Wechatpay-Timestamp":
                            map.put("timeStamp",allHeader.getValue());
                            break;
                        default:
                            break;
                    }
                    log.info("=="+allHeader.getName()+","+allHeader.getValue());
                }
                log.info("开始第二次签名");
                String waitSignStr = weChatConfig.getAppid() + "\n"
                        + map.get("timeStamp") + "\n"
                        + map.get("nonceStr") + "\n"
                        + "prepay_id=" + map.get("prepay_id") + "\n";
                log.info("待签名字符串:\n{}",waitSignStr);
                Signature sign = Signature.getInstance("SHA256withRSA");
                sign.initSign(weChatConfig.getPrivateKey());
                sign.update(waitSignStr.getBytes(StandardCharsets.UTF_8));
                String paySign = Base64.encode(sign.sign());
                map.put("signType","RSA");
                map.put("paySign",paySign);
                return map;
            } else {
                System.err.println("微信支付错误信息" + EntityUtils.toString(httpEntity));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
